package com.esyoga.yoyoga.realm;
import com.esyoga.yoyoga.pojo.TPlatform;
import com.esyoga.yoyoga.service.GymVerifyService;
import com.esyoga.yoyoga.service.PlatformVerifyService;
import com.esyoga.yoyoga.service.StudentVerifyService;
import com.esyoga.yoyoga.service.TrainerVerifyService;
import com.esyoga.yoyoga.util.UsernamePasswordByUserTypeToken;
import lombok.Data;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;

/**
 * @author YangTao
 */
@Data
public class UserRealm extends AuthorizingRealm {
    @Resource
    private GymVerifyService gymVerifyService;
    @Resource
    private StudentVerifyService studentVerifyService;
    @Resource
    private TrainerVerifyService trainerVerifyService;
    @Resource
    private PlatformVerifyService platformVerifyService;

    //授权的方法：从数据库中读取当前用户有哪些权限
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("正在查询用户权限");
        // 能进入这里说明用户已经通过验证了
        Subject currentUser = SecurityUtils.getSubject();
        Session session = currentUser.getSession();
        int userType = (int)session.getAttribute("userType");
        //因为项目设计统一张表中的用户只有一个角色，所以不单独建表维护用户角色的关系。userType与role一对一
        Set<String>roles = new HashSet<>();

        String phone = (String)principalCollection.getPrimaryPrincipal();
        System.out.println("当前验证账号："+phone+"------");
        //根据用户类型查询该类型拥有的权限
        switch(userType) {
            case 0:
                roles.add("student");
                break;
            case 1:
                roles.add("trainer");
                break;
            case 2:
                roles.add("gym");
                break;
            case 3:
                roles.add("admin");
                break;
            default:roles.add("NULL");
        }
        // 根据角色模拟给权限
        Set<String> perms = new HashSet<>();
        perms.add("user:delete");
        for (String s:roles) {
            System.out.println("匹配的权限："+s);
        }

        //添加角色
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
        // 权限添加到info
        info.addStringPermissions(perms);
        return info;
    }

    // 认证方法：从数据库中查询当前用户的信息（账号、密码等）
    // 如果该方法返回值是null.代表没在数据库查到
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {
        //强转成自定义token
        UsernamePasswordByUserTypeToken token = (UsernamePasswordByUserTypeToken)authenticationToken;
        System.out.println("正在进行认证");
        // token中获取账号
        String account = (String) token.getPrincipal();
        System.out.println("用户提交的账号：" + account);
        // 获取密码(凭证)
        String pwd = new String((char[]) token.getCredentials());
        System.out.println("获取的密码：" + pwd);
        //获取用户类型
        Subject currentUser = SecurityUtils.getSubject();
        Session currentUserSession = currentUser.getSession();
        int userType = (int) currentUserSession.getAttribute("userType");
        System.out.println("userTyperealm:"+userType);
        String password = null;
        //根据不同些权限查不痛的角色密码信息
        switch(userType) {
            case 0:
                password = studentVerifyService.findPasswordByPhone(account);
                break;
            case 1:
                password = trainerVerifyService.findTrainerPasswordByPhone(account);
                break;
            case 2:
                password = gymVerifyService.findTGymPasswordByPhone(account);
                break;
            case 3:
                TPlatform platform = platformVerifyService.findPlatformByAccount(account);
                if(platform!=null){
                    password = platform.getpPassword();
                }
                break;
            default:
                break;
        }
        //不使用加密
        SimpleAuthenticationInfo info =
                new SimpleAuthenticationInfo(account, password, getName());

        return info;
    }

}
